Skip to content

Add LargeYeagerTransferCoefficients bulk flux formulation#162

Open
simone-silvestri wants to merge 18 commits intomainfrom
ss/ncar-bulk-formulae
Open

Add LargeYeagerTransferCoefficients bulk flux formulation#162
simone-silvestri wants to merge 18 commits intomainfrom
ss/ncar-bulk-formulae

Conversation

@simone-silvestri
Copy link
Copy Markdown
Member

@simone-silvestri simone-silvestri commented Apr 15, 2026

Summary

Refactor CoefficientBasedFluxes to cleanly support the Large & Yeager (2004, 2009)
stability-corrected bulk algorithm alongside constant and polynomial coefficients.

The previous API used separate keyword arguments (drag_coefficient, heat_transfer_coefficient,
vapor_flux_coefficient), which made it awkward to pass coupled coefficient formulations like
the L&Y algorithm — where all three coefficients are computed together from a single set of
parameters. To resolve this, the three separate fields are replaced by a single
transfer_coefficients field that accepts either a SimilarityScales tuple (for independent
constant or callable coefficients) or a LargeYeagerTransferCoefficients object (for the
coupled L&Y formulation). The von_karman_constant is moved from CoefficientBasedFluxes
into LargeYeagerTransferCoefficients, where it is actually used.

Changes

  • Replace drag_coefficient, heat_transfer_coefficient, vapor_flux_coefficient with a single transfer_coefficients keyword
  • Add LargeYeagerTransferCoefficients implementing the full L&Y 2004/2009 algorithm with Monin-Obukhov stability corrections (OMIP-2 protocol)
  • Add PolynomialNeutralDragCoefficient for wind-speed-dependent neutral drag
  • Add LinearStableStabilityFunction and large_yeager_stability_functions for L&Y-style stability corrections
  • Move von_karman_constant from CoefficientBasedFluxes into LargeYeagerTransferCoefficients
  • Export SimilarityScales as the public container for transfer coefficients

New API

# Constant coefficients
CoefficientBasedFluxes(transfer_coefficients = SimilarityScales(2e-3, 1e-3, 1e-3))

# Polynomial drag with constant scalar coefficients
CoefficientBasedFluxes(transfer_coefficients = SimilarityScales(PolynomialNeutralDragCoefficient(), 1e-3, 1e-3))

# Full Large & Yeager stability-corrected algorithm
CoefficientBasedFluxes(transfer_coefficients = LargeYeagerTransferCoefficients(),
                       solver_stop_criteria = FixedIterations(5))

References

  • Large, W.G. & Yeager, S.G. (2004): NCAR/TN-460+STR
  • Large, W.G. & Yeager, S.G. (2009): Climate Dynamics, 33, 341-364

Test plan

  • Unit tests for PolynomialNeutralDragCoefficient (bounds, cap, monotonicity, Float32)
  • Unit tests for LinearStableStabilityFunction and large_yeager_stability_functions
  • Constructor tests for LargeYeagerTransferCoefficients
  • Integration tests: constant, polynomial, and L&Y coefficients produce finite fluxes
  • CI passes

@simone-silvestri simone-silvestri force-pushed the ss/ncar-bulk-formulae branch 2 times, most recently from ef91327 to 088e2dc Compare April 15, 2026 12:03
@simone-silvestri simone-silvestri changed the base branch from ss/patch-1 to main April 15, 2026 12:03
@simone-silvestri simone-silvestri changed the title Add NCAR/Large-Yeager bulk formulae Add transfer-coefficient bulk flux formulation (Large & Yeager 2004) Apr 15, 2026
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 15, 2026

Codecov Report

❌ Patch coverage is 66.36364% with 37 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
...Computations/coefficient_based_turbulent_fluxes.jl 63.54% 35 Missing ⚠️
...Computations/similarity_theory_turbulent_fluxes.jl 85.71% 2 Missing ⚠️

📢 Thoughts on this report? Let us know!

Comment thread src/EarthSystemModels/InterfaceComputations/transfer_coefficient_fluxes.jl Outdated
Comment thread src/EarthSystemModels/InterfaceComputations/transfer_coefficient_fluxes.jl Outdated
@simone-silvestri
Copy link
Copy Markdown
Member Author

Initially everything was prefixed by NCAR but I think it is not very nice to have it in a name. I ll think a bit more at the names

@glwagner
Copy link
Copy Markdown
Member

There is a simpler, non-iterative way to implement this. See here: https://github.com/NumericalEarth/Breeze.jl/blob/main/src/BoundaryConditions/polynomial_bulk_coefficient.jl

@simone-silvestri
Copy link
Copy Markdown
Member Author

Interesting. This is a regression to approximate the iterations looks like? We can also add this formulation to the model, that fits very cleanly with the CoefficientBasedFluxes, just need to make the coefficients polynomial.

For OMIP compliance we need the iterative fluxes unfortunately to be exactly equal to the OMIP2 procedure. I would like to make sure the biases are not because of different forcing. I think I can add this whole machinery by just making some changes to generalize the CoefficientBasedFluxes which becomes cleaner.

Introduce `CoefficientBasedFluxes` with a unified `transfer_coefficients`
interface that accepts either `SimilarityScales` (constant or callable
coefficients) or `LargeYeagerTransferCoefficients` (full L&Y 2004/2009
stability-corrected algorithm). Add `PolynomialNeutralDragCoefficient`,
`LinearStableStabilityFunction`, and `large_yeager_stability_functions`.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@simone-silvestri simone-silvestri changed the title Add transfer-coefficient bulk flux formulation (Large & Yeager 2004) Add LargeYeagerTransferCoefficients bulk flux formulation Apr 16, 2026
@simone-silvestri
Copy link
Copy Markdown
Member Author

Ok, this might be better now.

@glwagner
Copy link
Copy Markdown
Member

Interesting. This is a regression to approximate the iterations looks like? We can also add this formulation to the model, that fits very cleanly with the CoefficientBasedFluxes, just need to make the coefficients polynomial.

It's a regression to the bulk Ri and stability parameter. If the stability parameter is known then the fluxes can be evaluated directly with no iteration.

I guess it is simply an approximation solution to the flux inversion. It's fairly accurate as demonstrated by that paper.

The question is basically how many flux models we need? If we want something that uses polynomials approximations, it might make sense to go all the way to avoiding iteration. But I understand if you really need LY09 exactly.

@simone-silvestri
Copy link
Copy Markdown
Member Author

simone-silvestri commented Apr 17, 2026

I agree that maybe that formulation is probably better since it is a single sweep. I can test the difference and see if we can just keep the simple one-shot formulation. I have restructured the PR to use CoefficientBasedFluxes so removing the L&Y formulation should be a matter of only deleting one method (evaluate_coefficients(::LargeYeagerTransferCoefficients)).

@glwagner
Copy link
Copy Markdown
Member

I agree that maybe that formulation is probably better since it is a single sweep. I can test the difference and see if we can just keep the simple one-shot formulation. I have restructured the PR to use CoefficientBasedFluxes so removing the L&Y formulation should be a matter of only deleting one method (evaluate_coefficients(::LargeYeagerTransferCoefficients)).

oh neat

@simone-silvestri
Copy link
Copy Markdown
Member Author

These new fluxes can be seen in action here https://numericalearth.github.io/NumericalEarthDocumentation/previews/PR162/interface_fluxes/
In particular:
image

@simone-silvestri simone-silvestri requested a review from jagoosw May 1, 2026 10:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants